#include <AknsDrawUtils.h>
#include <gulicon.h>
#include "CharUtils.h"
#include "SingaporeBusDocument.h"
#include "SingaporeBusDrawItemsSG.h"
#include "CSingaporeBusGenericView.h"
#include "FunTrace.h"
#include "MathUtils.h"


CSingaporeBusDrawItemsSG::CSingaporeBusDrawItemsSG() : iPrimaryFont(NULL), iSecondaryFont(NULL), iValidSkinTextColor(EFalse)
	{
	
	}

const CFont* CSingaporeBusDrawItemsSG::PrimaryFont() const
{
	return iPrimaryFont;
}

void CSingaporeBusDrawItemsSG::ConstructL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	CAknDoubleGraphicStyleListBox* refListBox = new (ELeave) CAknDoubleGraphicStyleListBox;
	refListBox->ConstructL(NULL, 0);
	refListBox->SetRect(TRect(0,0,0,0));
	TFontSpec primaryFontSpec = refListBox->ItemDrawer()->ColumnData()->SubCellFont(1)->FontSpecInTwips();
	TFontSpec secondaryFontSpec = refListBox->ItemDrawer()->ColumnData()->SubCellFont(2)->FontSpecInTwips();
	delete refListBox;
	User::LeaveIfError(CCoeEnv::Static()->ScreenDevice()->GetNearestFontInTwips(iPrimaryFont,primaryFontSpec));
	User::LeaveIfError(CCoeEnv::Static()->ScreenDevice()->GetNearestFontInTwips(iSecondaryFont,secondaryFontSpec));
	}

const CFont* CSingaporeBusDrawItemsSG::SecondaryFont() const
{
	return iSecondaryFont;
}


static void AppendFormatDistanceL(TDes& aBuf, TReal32 aDistance)
	{
	if(aDistance >= 1000)
		{
		aBuf.AppendFormat(_L("%.1fkm"), (double)aDistance/1000);
		}
	else
		{
		aBuf.AppendFormat(_L("%.0fm"), (double)aDistance);
		}
	}

void CSingaporeBusDrawItemsSG::BeginDrawItemL(
		CSingaporeBusListBoxItemDrawer* aDrawer,
		const TRect& aRect, 
		TBool aItemIsCurrent,
		TRect& aClientRect) const
	{
	iDrawer = aDrawer;
	iItemIsCurrent = aItemIsCurrent;
	aClientRect = aRect;
	if(iDrawer->ListBox()->ScrollBarFrame() && iDrawer->ListBox()->ScrollBarFrame()->VerticalScrollBar() && iDrawer->ListBox()->ScrollBarFrame()->VerticalScrollBar()->IsVisible())
		aClientRect.iBr.iX -= iDrawer->ListBox()->ScrollBarFrame()->VerticalScrollBar()->Size().iWidth;
	TTime currentTime;
	currentTime.HomeTime();
	iIntervalSincePreviousCurrentItemChange = currentTime.MicroSecondsFrom( aDrawer->TimePreviousCurrentItemChange() );
	if(iItemIsCurrent && iDrawer->ListBox()->Dragging())
		{
		aClientRect.iTl.iX += Min(0, iDrawer->ListBox()->DraggingOffset().iX);
		iIntervalSincePreviousCurrentItemChange = TTimeIntervalMicroSeconds(KMaxTInt64); // no marquee
		}
	}



void CSingaporeBusDrawItemsSG::DrawBusStopItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const TStation* aStation,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
	{
	CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
	TBool isFavorite = (doc->FindFavorite(aStation) != KErrNotFound);
	TInt iconIndex = -1;
	if(isFavorite)
		{
		if(doc->iOriginStation == aStation)
			iconIndex = 3;
		else if(doc->iDestinationStation == aStation)
			iconIndex = 4;
		else
			iconIndex = 0;
		}
	else
		{
		if(doc->iOriginStation == aStation)
			iconIndex = 1;
		else if(doc->iDestinationStation == aStation)
			iconIndex = 2;
		}
	
	TRect clientItemRect;
	BeginDrawItemL(
			aDrawer,
			aActualItemRect,
			aItemIsCurrent, 
			clientItemRect
			);
	
	TRect line1, line2, line3;
	TRect stopNumberRect, stopAddress2Rect, servicesRect, distanceRect, stopAddressRect, iconRect, nicknameRect, directionRect;
	SplitRectVert(clientItemRect,
			PrimaryFont()->FontMaxHeight(),
			SecondaryFont()->FontMaxHeight(),
			line1, line2, line3);
	SplitRectHorz(line1,
			PrimaryFont()->CharWidthInPixels('0')*7,
			stopNumberRect, stopAddress2Rect);
	if(iconIndex != -1)
		SplitRectHorz(
				TRect(stopAddress2Rect),
				-PrimaryFont()->CharWidthInPixels('0'),
				stopAddress2Rect, iconRect
				);
	SplitRectHorz(line2,
			PrimaryFont()->CharWidthInPixels('0')*7,
			distanceRect, stopAddressRect);
	ShrinkToSize(stopNumberRect, PrimaryFont()->CharWidthInPixels('0')*6, PrimaryFont()->FontMaxHeight() );
	
	const TInt directionRectSideLength = Min(line3.Height(), line1.Height());
	SplitRectHorz(line3,
			directionRectSideLength/2+stopNumberRect.Width()/2,
			directionRect, servicesRect);
	directionRect.iTl.iX = directionRect.iBr.iX - directionRectSideLength;
	ShrinkToSize(directionRect, directionRectSideLength, directionRectSideLength );
	
	
	DrawBackgroundL(
			aActualItemRect);
	
	DrawStationNumberL(
			stopNumberRect, PrimaryFont(),
			aStation);
	
	/*TBuf<512> buf;
	buf.Format(_L("%d, %d, %d | %d, %d, %d | %S"),
			aDrawer->ListBox()->iMaxTimeFrame, aDrawer->ListBox()->iLastTimeFrame, aDrawer->ListBox()->iCountFrames == 0 ? 0 : aDrawer->ListBox()->iAccumulatedTimeFrame/aDrawer->ListBox()->iCountFrames,
			aDrawer->ListBox()->iAllocMem, aDrawer->ListBox()->iHeapSize, aDrawer->ListBox()->iLimitHeapSize,
			narrowToWideLC(aStation->iAddress2));
	CleanupStack::PopAndDestroy();*/
	
	DrawTextL(
			stopAddress2Rect, PrimaryFont(),
			aStation->iAddress2);
	
	if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
		{
		DrawDistanceL(
				distanceRect, SecondaryFont(),
				doc->iPosition, aStation->iCoord);
		
#ifndef __SERIES60_3X__
			
			DrawDirectionL(
					directionRect, SecondaryFont(),
					doc->iPosition, aStation->iCoord, doc->iMagneticNorthData.iAngleFromMagneticNorth);
#endif
		}
	
	DrawTextL(
			stopAddressRect, SecondaryFont(),
			aStation->iAddress);
	const CFont* servicesFont = ((const CFont*)AknLayoutUtils::LayoutFontFromId(EAknLogicalFontPrimarySmallFont));
	DrawStationServicesL(
			servicesRect, servicesFont,
			aStation);
	if(iconIndex != -1)
		{
		DrawIconL(
				iconRect,
				iconIndex);
		}
	EndDrawItemL();
	}



void CSingaporeBusDrawItemsSG::DrawBusServiceItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CArrivalTimeItem* aArrivalTime,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
	{

	TBuf<512> buf;
	CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();

	TBool isFavorite = aArrivalTime->iService ? (doc->FindFavorite(aArrivalTime->iService) != KErrNotFound) : EFalse;
	
	TRect clientItemRect;
	BeginDrawItemL(
			aDrawer,
			aActualItemRect,
			aItemIsCurrent, 
			clientItemRect
			);
	
	TRect line1, line2, line3;
	TRect serviceNameRect, serviceDirectionRect, stopNumberRect, iconRect, distanceRect, stopLocationRect, arrivalTimeRect;
	SplitRectVert(clientItemRect,
			PrimaryFont()->FontMaxHeight(),
			SecondaryFont()->FontMaxHeight(),
			line1, line2, line3);
	SplitRectHorz(line1,
			PrimaryFont()->CharWidthInPixels('0')*7,
			serviceNameRect, serviceDirectionRect);
	if(isFavorite)
		SplitRectHorz(
				TRect(serviceDirectionRect),
				-PrimaryFont()->CharWidthInPixels('0'),
				serviceDirectionRect, iconRect
				);
	SplitRectHorz(line2,
			PrimaryFont()->CharWidthInPixels('0')*7,
			distanceRect, stopLocationRect);
	arrivalTimeRect = line3;
	arrivalTimeRect.iTl.iX = serviceNameRect.Center().iX;
	ShrinkToSize(serviceNameRect, PrimaryFont()->CharWidthInPixels('0')*6, PrimaryFont()->FontMaxHeight() );
	
	DrawBackgroundL(
			aActualItemRect);
	DrawServiceNameL(
			serviceNameRect, PrimaryFont(),
			aArrivalTime->iService);
	buf.Format(_L("to %S"), narrowToWideLC(aArrivalTime->iService->iTo));
	CleanupStack::PopAndDestroy();
	DrawTextL(
			serviceDirectionRect, PrimaryFont(),
			buf);
	if(aArrivalTime->iStation)
		{
		TBuf<512> buf;
		buf.Format(_L("%S"), narrowToWideLC(aArrivalTime->iStation->iAddress2));
		CleanupStack::PopAndDestroy(1);
		DrawTextL(
				stopLocationRect, SecondaryFont(),
				buf);
		if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
			DrawDistanceL(
					distanceRect, SecondaryFont(),
					doc->iPosition, aArrivalTime->iStation->iCoord);
		DrawArrivalTimeL(
				arrivalTimeRect, SecondaryFont(),
				aArrivalTime);
		}
	if(isFavorite)
		DrawIconL(
				iconRect,
				0);
	EndDrawItemL();

	
	}

void CSingaporeBusDrawItemsSG::DrawBusServiceArrivalTimeWithStationItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CArrivalTimeItem* aArrivalTime,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{

		TBuf<512> buf;
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();

		TBool isFavorite = (aArrivalTime->iService && aArrivalTime->iStation) ? (doc->FindFavorite(aArrivalTime->iStation, aArrivalTime->iService) != KErrNotFound) : EFalse;
		
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);
		
		TRect line1, line2, line3;
		TRect serviceNameRect, serviceDirectionRect, stopNumberRect, iconRect, distanceRect, stopLocationRect, arrivalTimeRect;
		SplitRectVert(clientItemRect,
				PrimaryFont()->FontMaxHeight(),
				SecondaryFont()->FontMaxHeight(),
				line1, line2, line3);
		SplitRectHorz(line1,
				PrimaryFont()->CharWidthInPixels('0')*7,
				serviceNameRect, serviceDirectionRect);
		if(isFavorite)
			SplitRectHorz(
					TRect(serviceDirectionRect),
					-PrimaryFont()->CharWidthInPixels('0'),
					serviceDirectionRect, iconRect
					);
		SplitRectHorz(line2,
				PrimaryFont()->CharWidthInPixels('0')*7,
				distanceRect, stopLocationRect);
		arrivalTimeRect = line3;
		arrivalTimeRect.iTl.iX = serviceNameRect.Center().iX;
		ShrinkToSize(serviceNameRect, PrimaryFont()->CharWidthInPixels('0')*6, PrimaryFont()->FontMaxHeight() );
		
		DrawBackgroundL(
				aActualItemRect);
		DrawServiceNameL(
				serviceNameRect, PrimaryFont(),
				aArrivalTime->iService);
		buf.Format(_L("to %S"), narrowToWideLC(aArrivalTime->iService->iTo));
		CleanupStack::PopAndDestroy();
		DrawTextL(
				serviceDirectionRect, PrimaryFont(),
				buf);
		if(aArrivalTime->iStation)
			{
			TBuf<512> buf;
			buf.Format(_L("\xF808 %S"), narrowToWideLC(aArrivalTime->iStation->iAddress2));
			CleanupStack::PopAndDestroy(1);
			DrawTextL(
					stopLocationRect, SecondaryFont(),
					buf);
			if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
				DrawDistanceL(
						distanceRect, SecondaryFont(),
						doc->iPosition, aArrivalTime->iStation->iCoord);
			DrawArrivalTimeL(
					arrivalTimeRect, SecondaryFont(),
					aArrivalTime);
			}
		if(isFavorite)
			DrawIconL(
					iconRect,
					0);
		EndDrawItemL();

		
		}

void CSingaporeBusDrawItemsSG::DrawAdBannerL(CSingaporeBusListBoxItemDrawer* aDrawer, CFbsBitmap* aBitmap,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);
		
		CWindowGc& gc = *iDrawer->Gc();
		DrawBackgroundL(
				aActualItemRect);
		TPoint point (
		Max(0, clientItemRect.iTl.iX + (clientItemRect.Size().iWidth - aBitmap->SizeInPixels().iWidth) / 2),
		Max(0, clientItemRect.iTl.iY + (clientItemRect.Size().iHeight - aBitmap->SizeInPixels().iHeight) / 2)
		);
		gc.BitBlt(point, aBitmap, TRect( 0, 0, Min(clientItemRect.Size().iWidth, aBitmap->SizeInPixels().iWidth), Min(clientItemRect.Size().iHeight, aBitmap->SizeInPixels().iHeight) ));
		EndDrawItemL();
		}

void CSingaporeBusDrawItemsSG::DrawAdTextL(CSingaporeBusListBoxItemDrawer* aDrawer, const TDesC& aText,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);
		
		DrawBackgroundL(
				aActualItemRect);
		DrawTextL(
				clientItemRect, SecondaryFont(),
				aText, CGraphicsContext::ECenter);
		EndDrawItemL();
		}

void CSingaporeBusDrawItemsSG::DrawBusServiceArrivalTimeItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CArrivalTimeItem* aArrivalTime,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
	{
	TBuf<512> buf;
	CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();

	TBool isFavorite = aArrivalTime->iService && aArrivalTime->iStation ? (doc->FindFavorite(aArrivalTime->iStation, aArrivalTime->iService) != KErrNotFound) : EFalse;
	
	TRect clientItemRect;
	BeginDrawItemL(
			aDrawer,
			aActualItemRect,
			aItemIsCurrent, 
			clientItemRect
			);
	
	TRect line1, line2;
	TRect serviceNameRect, serviceDirectionRect, iconRect, distanceRect, stopAddressRect, arrivalTimeRect;
	SplitRectVert(clientItemRect, PrimaryFont()->FontMaxHeight(), line1, line2);
	SplitRectHorz(line1,
			PrimaryFont()->CharWidthInPixels('0')*7,
			serviceNameRect, serviceDirectionRect);
	if(isFavorite)
		SplitRectHorz(
				TRect(serviceDirectionRect),
				-PrimaryFont()->CharWidthInPixels('0'),
				serviceDirectionRect, iconRect
				);
	SplitRectHorz(line2,
			PrimaryFont()->CharWidthInPixels('0')*7,
			distanceRect, arrivalTimeRect);
	ShrinkToSize(serviceNameRect, PrimaryFont()->CharWidthInPixels('0')*6, PrimaryFont()->FontMaxHeight() );
	
	DrawBackgroundL(
			aActualItemRect);
	DrawServiceNameL(
			serviceNameRect, PrimaryFont(),
			aArrivalTime->iService);
	/*
	buf.Format(_L("%d, %d, %d | to %S"), aDrawer->ListBox()->iMaxTimeFrame, aDrawer->ListBox()->iLastTimeFrame, aDrawer->ListBox()->iCountFrames == 0 ? 0 : aDrawer->ListBox()->iAccumulatedTimeFrame/aDrawer->ListBox()->iCountFrames, narrowToWideLC(aArrivalTime->iService->iTo));
	CleanupStack::PopAndDestroy();*/
	buf.Format(_L("to %S"), narrowToWideLC(aArrivalTime->iService->iTo));
	CleanupStack::PopAndDestroy();
	DrawTextL(
			serviceDirectionRect, PrimaryFont(),
			buf);
	if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
		DrawDistanceL(
				distanceRect, SecondaryFont(),
				doc->iPosition, aArrivalTime->iStation->iCoord);
	DrawArrivalTimeL(
			arrivalTimeRect, SecondaryFont(),
			aArrivalTime);
	if(isFavorite)
		DrawIconL(
				iconRect,
				0);
	EndDrawItemL();


	}


void CSingaporeBusDrawItemsSG::DrawBusServiceRouteItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CArrivalTimeItem* aArrivalTime,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
	{
	
	CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();

	TBool isFavorite = (aArrivalTime->iService && aArrivalTime->iStation) ? (doc->FindFavorite(aArrivalTime->iStation, aArrivalTime->iService) != KErrNotFound) : EFalse;
	
	TRect clientItemRect;
	BeginDrawItemL(
			aDrawer,
			aActualItemRect,
			aItemIsCurrent, 
			clientItemRect
			);
	
	
	TBuf<512> buf;
	TRect line1, line2, line3;
	TRect stopNumberRect, stopAddress2Rect, iconRect, distanceRect, stopAddressRect, arrivalTimeRect;
	SplitRectVert(clientItemRect,
			PrimaryFont()->FontMaxHeight(),
			SecondaryFont()->FontMaxHeight(),
			line1, line2, line3);
	SplitRectHorz(line1,
			PrimaryFont()->CharWidthInPixels('0')*7,
			stopNumberRect, stopAddress2Rect);
	if(isFavorite)
		SplitRectHorz(
				TRect(stopAddress2Rect),
				-PrimaryFont()->CharWidthInPixels('0'),
				stopAddress2Rect, iconRect
				);
	SplitRectHorz(line2,
			PrimaryFont()->CharWidthInPixels('0')*7,
			distanceRect, stopAddressRect);
	arrivalTimeRect = line3;
	arrivalTimeRect.iTl.iX = stopNumberRect.Center().iX;
	ShrinkToSize(stopNumberRect, PrimaryFont()->CharWidthInPixels('0')*6, PrimaryFont()->FontMaxHeight() );
	
	DrawBackgroundL(
			aActualItemRect);
	DrawStationNumberL(
			stopNumberRect, PrimaryFont(),
			aArrivalTime->iStation);
	DrawTextL(
			stopAddress2Rect, PrimaryFont(),
			aArrivalTime->iStation->iAddress2);
	DrawTextL(
			stopAddressRect, SecondaryFont(),
			aArrivalTime->iStation->iAddress);
	if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
		DrawDistanceL(
				distanceRect, SecondaryFont(),
				doc->iPosition, aArrivalTime->iStation->iCoord);
	DrawArrivalTimeL(
			arrivalTimeRect, SecondaryFont(),
			aArrivalTime);
	DrawTextL(
			stopAddressRect, SecondaryFont(),
			aArrivalTime->iStation->iAddress);
	if(isFavorite)
		DrawIconL(
				iconRect,
				0);
	EndDrawItemL();


	
	
	}



void CSingaporeBusDrawItemsSG::DrawItineraryLegFromItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CJourneyPlannerOutput::CItinerary::CLeg* aLeg,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);

		/*TRect line1, line2, col1, col2;
		SplitRectHorz(clientItemRect, PrimaryFont()->CharWidthInPixels('0')*7, col1, col2);
		TRect journeyDistanceRect, locationRect, meansOfTransportRect, stopsCountRect, locationAddressRect;
		SplitRectVert(col2, col2.Height()/2,
				locationRect, locationAddressRect);
		SplitRectVert(col1,
				col1.Height()*2/3,
				meansOfTransportRect, stopsCountRect);*/

		
		TRect line1, line2, line3;
		SplitRectVert(clientItemRect,
				PrimaryFont()->FontMaxHeight(),
				SecondaryFont()->FontMaxHeight(),
				line1, line2, line3);
		TRect tempRect, meansOfTransportRect, stopsCountRect, locationRect, locationAddressRect, locationDistanceRect;
		SplitRectHorz(line1,
				PrimaryFont()->CharWidthInPixels('0')*7,
				meansOfTransportRect, locationRect);
		SplitRectHorz(line2,
				PrimaryFont()->CharWidthInPixels('0')*7,
				tempRect, locationAddressRect);
		SplitRectHorz(line3,
				PrimaryFont()->CharWidthInPixels('0')*7,
				stopsCountRect, locationDistanceRect);

		DrawBackgroundL(
				aActualItemRect);
		
		{
		aDrawer->Gc()->SetPenStyle(CGraphicsContext::ESolidPen);
		aDrawer->Gc()->SetPenColor(SkinTextColor());
		TPoint point[] =
		{
				TPoint(aActualItemRect.iTl.iX, aActualItemRect.iTl.iY),
				TPoint(aActualItemRect.iBr.iX, aActualItemRect.iTl.iY)
		};
		aDrawer->Gc()->DrawPolyLine(point, sizeof(point)/sizeof(point[0]));
		}
		
		TBuf<512> buf;
		
		if(aLeg->iFromStation)
			{
			buf.Format(_L("Board at %S (%S)"), narrowToWideLC(aLeg->iFromStation->iAddress2), narrowToWideLC(aLeg->iFromStation->iStationNumber));
			CleanupStack::PopAndDestroy(2);
			}
		else if (aLeg->iFromLocation)
			buf.Format(_L("Board at %S"), aLeg->iFromLocation);
		DrawTextL(
				locationRect, PrimaryFont(),
				buf);
		
		if(aLeg->iFromStation)
			{
			DrawTextL(
					locationAddressRect, SecondaryFont(),
					*narrowToWideLC(aLeg->iFromStation->iAddress));
			CleanupStack::PopAndDestroy();
			if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
				{
				TReal32 distance;
				doc->iPosition.Distance(aLeg->iFromStation->iCoord, distance);
				buf.Zero();
				buf.Append('(');
				AppendFormatDistanceL(buf, distance);
				buf.Append(')');
				DrawTextL(
						locationDistanceRect, SecondaryFont(),
						buf);
				}
			}
		
		
		if(aLeg->iService)
			{
			ShrinkToSize(meansOfTransportRect, PrimaryFont()->CharWidthInPixels('0')*6, PrimaryFont()->FontMaxHeight() );
			DrawServiceNameL(
					meansOfTransportRect, PrimaryFont(),
					aLeg->iService);
			}
		else if(aLeg->iServiceDesc)
			DrawTextL(
					meansOfTransportRect, PrimaryFont(),
					*aLeg->iServiceDesc, CGraphicsContext::ECenter);
		
		
		buf.Format(_L("%d stop"), aLeg->iCountStops);
		if(aLeg->iCountStops > 1)
			buf.Append(TChar('s'));
		DrawTextL(
				stopsCountRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		
		
		EndDrawItemL();

		
		}


void CSingaporeBusDrawItemsSG::DrawItineraryLegToItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CJourneyPlannerOutput::CItinerary::CLeg* aLeg,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{

		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);
		
		/*TRect line1, line2, col1, col2;
		SplitRectHorz(clientItemRect, PrimaryFont()->CharWidthInPixels('0')*7, col1, col2);
		TRect journeyDistanceRect, locationRect, journeyDurationRect, legFareRect, locationAddressRect;
		SplitRectVert(col2, col2.Height()/2,
				locationRect, locationAddressRect);
		SplitRectVert(col1,
				col1.Height()/3, col1.Height()/3,
				journeyDistanceRect, journeyDurationRect, legFareRect);*/

		TRect line1, line2, line3;
		TRect journeyDistanceRect, locationRect, journeyDurationRect, legFareRect, locationAddressRect, locationDistanceRect;
		SplitRectVert(clientItemRect,
				PrimaryFont()->FontMaxHeight(),
				SecondaryFont()->FontMaxHeight(),
				line1, line2, line3);
		SplitRectHorz(line1,
				PrimaryFont()->CharWidthInPixels('0')*7,
				journeyDistanceRect, locationRect);
		SplitRectHorz(line2,
				PrimaryFont()->CharWidthInPixels('0')*7,
				journeyDurationRect, locationAddressRect);
		SplitRectHorz(line3,
				PrimaryFont()->CharWidthInPixels('0')*7,
				legFareRect, locationDistanceRect);

		DrawBackgroundL(
				aActualItemRect);
		TBuf<512> buf;
				
		if(aLeg->iToStation)
			{
			buf.Format(_L("Alight at %S (%S)"), narrowToWideLC( aLeg->iToStation->iAddress2 ), narrowToWideLC( aLeg->iToStation->iStationNumber ) );
			CleanupStack::PopAndDestroy(2);
			}
		else if (aLeg->iToLocation)
			buf.Format(_L("Alight at %S"), aLeg->iToLocation);
		DrawTextL(
				locationRect, PrimaryFont(),
				buf);
		
		if(aLeg->iToStation)
			{
			DrawTextL(
					locationAddressRect, SecondaryFont(),
					*narrowToWideLC( aLeg->iToStation->iAddress));
			CleanupStack::PopAndDestroy();
			if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
				{
				TReal32 distance;
				doc->iPosition.Distance(aLeg->iToStation->iCoord, distance);
				buf.Zero();
				buf.Append('(');
				AppendFormatDistanceL(buf, distance);
				buf.Append(')');
				DrawTextL(
						locationDistanceRect, SecondaryFont(),
						buf);
				}
			}
		
		
		buf.Zero();
		AppendFormatDistanceL(buf, aLeg->iDistance);
		DrawTextL(
				journeyDistanceRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		buf.Format(_L("%d min"), aLeg->iDuration/60);
		DrawTextL(
				journeyDurationRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		if(aLeg->iLegFare)
			{
			DrawTextL(
					legFareRect, SecondaryFont(),
					*aLeg->iLegFare, CGraphicsContext::ECenter);
			}
		
		EndDrawItemL();

		
		
		}

		
void CSingaporeBusDrawItemsSG::DrawItineraryLegWalkItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CJourneyPlannerOutput::CItinerary::CLeg* aLeg,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{

		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);
		
		/*TRect line1, line2, col1, col2;
		SplitRectHorz(clientItemRect, PrimaryFont()->CharWidthInPixels('0')*7, col1, col2);
		TRect journeyDistanceRect, locationRect, journeyDurationRect, titleRect, locationAddressRect;
		SplitRectVert(col2, col2.Height()/2,
				locationRect, locationAddressRect);
		SplitRectVert(col1,
				col1.Height()/3, col1.Height()/3,
				titleRect, journeyDistanceRect, journeyDurationRect);*/

		TRect line1, line2, line3;
		TRect titleRect, journeyDistanceRect, locationRect, journeyDurationRect, legFareRect, locationAddressRect, locationDistanceRect;
		SplitRectVert(clientItemRect,
				PrimaryFont()->FontMaxHeight(),
				SecondaryFont()->FontMaxHeight(),
				line1, line2, line3);
		SplitRectHorz(line1,
				PrimaryFont()->CharWidthInPixels('0')*7,
				titleRect, locationRect);
		SplitRectHorz(line2,
				PrimaryFont()->CharWidthInPixels('0')*7,
				journeyDurationRect, locationAddressRect);
		SplitRectHorz(line3,
				PrimaryFont()->CharWidthInPixels('0')*7,
				legFareRect, locationDistanceRect);

		DrawBackgroundL(
				aActualItemRect);
		TBuf<512> buf;
		
		DrawTextL(
				titleRect, PrimaryFont(),
				_L("Walk"), CGraphicsContext::ECenter);

		{
		aDrawer->Gc()->SetPenStyle(CGraphicsContext::ESolidPen);
		aDrawer->Gc()->SetPenColor(SkinTextColor());
		TPoint point[] =
		{
				TPoint(aActualItemRect.iTl.iX, aActualItemRect.iTl.iY),
				TPoint(aActualItemRect.iBr.iX, aActualItemRect.iTl.iY)
		};
		aDrawer->Gc()->DrawPolyLine(point, sizeof(point)/sizeof(point[0]));
		}
		
		if(aLeg->iToStation)
			{
			buf.Format(_L("To %S (%S)"), narrowToWideLC(aLeg->iToStation->iAddress2), narrowToWideLC(aLeg->iToStation->iStationNumber));
			CleanupStack::PopAndDestroy(2);
			}
		else if (aLeg->iToLocation)
			buf.Format(_L("To %S"), aLeg->iToLocation);
		DrawTextL(
				locationRect, PrimaryFont(),
				buf);
		
		if(aLeg->iToStation)
			{
			DrawTextL(
					locationAddressRect, SecondaryFont(),
					*narrowToWideLC(aLeg->iToStation->iAddress));
			CleanupStack::PopAndDestroy();
			if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
				{
				TReal32 distance;
				doc->iPosition.Distance(aLeg->iToStation->iCoord, distance);
				buf.Zero();
				buf.Append('(');
				AppendFormatDistanceL(buf, distance);
				buf.Append(')');
				DrawTextL(
						locationDistanceRect, SecondaryFont(),
						buf);
				}
			}
		
		
		buf.Zero();
		AppendFormatDistanceL(buf, aLeg->iDistance);
		DrawTextL(
				journeyDistanceRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		buf.Format(_L("%d min"), aLeg->iDuration/60);
		DrawTextL(
				journeyDurationRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		
		EndDrawItemL();

		
		
		}		


void CSingaporeBusDrawItemsSG::DrawItineraryTotalItemL(CSingaporeBusListBoxItemDrawer* aDrawer, const CJourneyPlannerOutput::CItinerary* aItinerary,
		TInt aItemIndex, const TRect& aActualItemRect,
		TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
		TBool aItemIsSelected) const
		{
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		
		TRect clientItemRect;
		BeginDrawItemL(
				aDrawer,
				aActualItemRect,
				aItemIsCurrent, 
				clientItemRect
				);
		
		
		/*TRect line1, line2, col1, col2;
		SplitRectHorz(clientItemRect, PrimaryFont()->CharWidthInPixels('0')*7, col1, col2);
		TRect distanceRect, durationRect, fareRect, titleRect;
		titleRect = col2;
		SplitRectVert(col1,
				col1.Height()/3, col1.Height()/3,
				distanceRect, durationRect, fareRect);*/
		
		TRect line1, line2, line3;
		TRect distanceRect, durationRect, fareRect, titleRect, temRect1, tempRect2;
		SplitRectVert(clientItemRect,
				PrimaryFont()->FontMaxHeight(),
				SecondaryFont()->FontMaxHeight(),
				line1, line2, line3);
		SplitRectHorz(line1,
				PrimaryFont()->CharWidthInPixels('0')*7,
				distanceRect, titleRect);
		SplitRectHorz(line2,
				PrimaryFont()->CharWidthInPixels('0')*7,
				durationRect, temRect1);
		SplitRectHorz(line3,
				PrimaryFont()->CharWidthInPixels('0')*7,
				fareRect, tempRect2);

		DrawBackgroundL(
				aActualItemRect);

		{
		aDrawer->Gc()->SetPenStyle(CGraphicsContext::ESolidPen);
		aDrawer->Gc()->SetPenColor(SkinTextColor());
		TPoint point[] =
		{
				TPoint(aActualItemRect.iTl.iX, aActualItemRect.iTl.iY),
				TPoint(aActualItemRect.iBr.iX, aActualItemRect.iTl.iY)
		};
		aDrawer->Gc()->DrawPolyLine(point, sizeof(point)/sizeof(point[0]));
		}
	
		DrawTextL(
				titleRect, PrimaryFont(),
				_L("Total solution"));
		
		TBuf<512> buf;
		buf.Zero();
		AppendFormatDistanceL(buf, aItinerary->iDistance);
		DrawTextL(
				distanceRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		buf.Format(_L("%d min"), aItinerary->iDuration/60);
		DrawTextL(
				durationRect, SecondaryFont(),
				buf, CGraphicsContext::ECenter);
		if(aItinerary->iFare)
			{
			DrawTextL(
					fareRect, SecondaryFont(),
					*aItinerary->iFare, CGraphicsContext::ECenter);
			}
		
		EndDrawItemL();
		
		}



void CSingaporeBusDrawItemsSG::EndDrawItemL() const
	{
	
	}

void CSingaporeBusDrawItemsSG::DrawServiceNameL(
		const TRect& aRect, const CFont* aFont,
		const TService* aService) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		TBool marqueeCompleted = EFalse;
		gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( (aService->iOperator == _L8("SBST")) ? KRgbRed : KRgbGray );
		gc.SetPenStyle(CGraphicsContext::ENullPen);
		gc.DrawRect(aRect);
		gc.SetBrushStyle(CGraphicsContext::ENullBrush);
		gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor( (aService->iOperator == _L8("SBST")) ? KRgbWhite : KRgbBlack );
		DrawMarqueeText(
				&gc, aFont,
				*narrowToWideLC(aService->iName),
				aRect,
				(aRect.Height() + aFont->AscentInPixels()) / 2,
				CGraphicsContext::ECenter,
				0,
				iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
		CleanupStack::PopAndDestroy();
		if(!marqueeCompleted)
			iDrawer->ScheduleRedrawL(1000000/30);
		}


void CSingaporeBusDrawItemsSG::DrawStationNicknameL(
		const TRect& aRect, const CFont* aFont,
		const TStation* aStation) const
		{
		
		CWindowGc& gc = *iDrawer->Gc();
		TBool marqueeCompleted = EFalse;
		DrawMarqueeText(
				&gc, aFont,
				*narrowToWideLC(aStation->iNickname),
				aRect,
				(aRect.Height() + aFont->AscentInPixels()) / 2,
				CGraphicsContext::ECenter,
				0,
				iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
		CleanupStack::PopAndDestroy();
		if(!marqueeCompleted)
			iDrawer->ScheduleRedrawL(1000000/30);
			
		}

void CSingaporeBusDrawItemsSG::DrawStationServices2L(
		const TRect& aRect, const CFont* aFont,
		const TStation* aStation) const
		{
		const TInt singleServiceWidth = aFont->CharWidthInPixels('0')*6;
		const TInt servicesWidth = (aStation->iServicesEnd - aStation->iServicesBeg)*singleServiceWidth;
		CWindowGc& gc = *iDrawer->Gc();
		TBool marqueeCompleted = EFalse;
		TRect drawRect;
		TInt offset;
		gc.SetBrushStyle(CGraphicsContext::ENullBrush);
		gc.SetPenColor(SkinTextColor());
		DrawMarqueeGeneric(
				&gc, aFont,
				servicesWidth,
				aRect,
				(aRect.Height() + aFont->AscentInPixels()) / 2,
				CGraphicsContext::ECenter,
				0,
				iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64),
				offset, drawRect,
				marqueeCompleted);

		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
		gc.SetBrushColor(KRgbBlack);
		TInt thRectLeft;
		const TInt firstServiceIndex =  aStation->iServicesBeg + Max(0, -offset/singleServiceWidth);
		const TInt thRectOffset = offset > 0 ? offset : - ( (-offset) % singleServiceWidth );
		for(
			TInt i = firstServiceIndex ;
			i < aStation->iServicesEnd &&
			(thRectLeft = aRect.iTl.iX + (i - firstServiceIndex)*singleServiceWidth + thRectOffset) < drawRect.iBr.iX;
			++i)
			{
			TDesC8& serviceKey = doc->iStationServiceKeys[i];
			TPtrC8 serviceName = serviceKey.Left( serviceKey.Locate(' ') );
			TInt rectLeft = Max(aRect.iTl.iX, thRectLeft);
			TInt thRectRight = thRectLeft + aFont->CharWidthInPixels('0')*5;
			TInt rectRight = Min(drawRect.iBr.iX, thRectRight);
			TRect rect = aRect;
			rect.iTl.iX = rectLeft;
			rect.iBr.iX = rectRight;
			rect.Shrink(0, aFont->FontMaxHeight()/10);
			const TService* service = NULL;
			{
			TBuf8<15> serviceKeyUpper(serviceKey);
			serviceKeyUpper.UpperCase();
			TService target = { serviceKeyUpper };
			TInt ret = doc->iServicesSortedByServiceKey.SpecificFindInOrder(&target, TLinearOrder<const TService*>(&CSingaporeBusDocument::TLinearOrder_Service), EArrayFindMode_Any);
			service = (ret != KErrNotFound) ? doc->iServicesSortedByServiceKey[ret] : NULL;
			}
			if(service)
				{
				//gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( (service->iOperator == _L8("SBST")) ? KRgbRed : KRgbGray );
				gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( (service->iOperator == _L8("SBST")) ? TRgb(255,100,100) : TRgb(208,208,208)  );
				gc.SetPenStyle(CGraphicsContext::ENullPen);
				gc.DrawRect(rect);
				TBuf<128> serviceNameW;
				serviceNameW.Copy(serviceName);
				TInt serviceNameWidth = aFont->TextWidthInPixels(serviceNameW);
				TInt textOffset = ((thRectRight - thRectLeft) - serviceNameWidth )/2;
				gc.UseFont(aFont);
				gc.SetBrushStyle(CGraphicsContext::ENullBrush);
				//gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor( (service->iOperator == _L8("SBST")) ? KRgbWhite : KRgbBlack );
				gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor( (service->iOperator == _L8("SBST")) ? KRgbWhite : TRgb(96,96,96) );
				gc.DrawText(serviceNameW, rect, (rect.Height() + aFont->AscentInPixels()) / 2, CGraphicsContext::ELeft, (thRectLeft - rectLeft) + textOffset);
				gc.DiscardFont();
				}
			}
		
		if(!marqueeCompleted)
			iDrawer->ScheduleRedrawL(1000000/30);
		}

void CSingaporeBusDrawItemsSG::DrawStationServicesL(
		const TRect& aRect, const CFont* aFont,
		const TStation* aStation) const
		{
		const TInt singleServiceWidth = aFont->CharWidthInPixels('0')*6;
		const TInt singleServiceHeight = aFont->FontMaxHeight();
		const TInt countLines = Max(1, aRect.Height()/singleServiceHeight);
		const TInt servicesWidth = ((aStation->iServicesEnd - aStation->iServicesBeg + (countLines - 1))/countLines)*singleServiceWidth;
		CWindowGc& gc = *iDrawer->Gc();
		TBool marqueeCompleted = EFalse;
		TRect drawRect;
		TInt offset;
		gc.SetBrushStyle(CGraphicsContext::ENullBrush);
		gc.SetPenColor(SkinTextColor());
		DrawMarqueeGeneric(
				&gc, aFont,
				servicesWidth,
				aRect,
				(aRect.Height() + aFont->AscentInPixels()) / 2,
				CGraphicsContext::ECenter,
				0,
				iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64),
				offset, drawRect,
				marqueeCompleted);

		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
		gc.SetBrushColor(KRgbBlack);
		TInt thRectLeft;
		const TInt firstServiceIndex =  aStation->iServicesBeg + Max(0, -offset/singleServiceWidth);
		const TInt firstCol =  Max(0, -offset/singleServiceWidth);
		const TInt thRectOffset = offset > 0 ? offset : - ( (-offset) % singleServiceWidth );
		for(
			TInt i = firstCol ;
			i * countLines < aStation->iServicesEnd - aStation->iServicesBeg &&
			(thRectLeft = aRect.iTl.iX + (i - firstCol ) * singleServiceWidth + thRectOffset) < drawRect.iBr.iX;
			++i)
			{
			for(TInt j = 0 ; j < countLines && i*countLines+j < aStation->iServicesEnd - aStation->iServicesBeg ; ++j)
				{
				TDesC8& serviceKey = doc->iStationServiceKeys[aStation->iServicesBeg + i*countLines+j];
				TPtrC8 serviceName = serviceKey.Left( serviceKey.Locate(' ') );
				TInt rectLeft = Max(aRect.iTl.iX, thRectLeft);
				TInt thRectRight = thRectLeft + aFont->CharWidthInPixels('0')*5;
				TInt rectRight = Min(drawRect.iBr.iX, thRectRight);
				TRect rect = aRect;
				rect.iTl.iY = aRect.iTl.iY + j*singleServiceHeight;
				rect.iBr.iY = rect.iTl.iY + singleServiceHeight;
				rect.iTl.iX = rectLeft;
				rect.iBr.iX = rectRight;
				rect.Shrink(0, aFont->FontMaxHeight()/10);
				const TService* service = NULL;
				{
				TBuf8<15> serviceKeyUpper(serviceKey);
				serviceKeyUpper.UpperCase();
				TService target = { serviceKeyUpper };
				TInt ret = doc->iServicesSortedByServiceKey.SpecificFindInOrder(&target, TLinearOrder<const TService*>(&CSingaporeBusDocument::TLinearOrder_Service), EArrayFindMode_Any);
				service = (ret != KErrNotFound) ? doc->iServicesSortedByServiceKey[ret] : NULL;
				}
				if(service)
					{
					//gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( (service->iOperator == _L8("SBST")) ? KRgbRed : KRgbGray );
					gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( (service->iOperator == _L8("SBST")) ? TRgb(255,100,100) : TRgb(208,208,208)  );
					gc.SetPenStyle(CGraphicsContext::ENullPen);
					gc.DrawRect(rect);
					TBuf<128> serviceNameW;
					serviceNameW.Copy(serviceName);
					TInt serviceNameWidth = aFont->TextWidthInPixels(serviceNameW);
					TInt textOffset = ((thRectRight - thRectLeft) - serviceNameWidth )/2;
					gc.UseFont(aFont);
					gc.SetBrushStyle(CGraphicsContext::ENullBrush);
					//gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor( (service->iOperator == _L8("SBST")) ? KRgbWhite : KRgbBlack );
					gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor( (service->iOperator == _L8("SBST")) ? KRgbWhite : TRgb(96,96,96) );
					gc.DrawText(serviceNameW, rect, (rect.Height() + aFont->AscentInPixels()) / 2, CGraphicsContext::ELeft, (thRectLeft - rectLeft) + textOffset);
					gc.DiscardFont();
					}
				}
			}
		
		if(!marqueeCompleted)
			iDrawer->ScheduleRedrawL(1000000/30);
		}

void CSingaporeBusDrawItemsSG::DrawStationNumberL(
		const TRect& aRect, const CFont* aFont,
		const TStation* aStation) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		TBool marqueeCompleted = EFalse;
		gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor(TRgb(0, 163, 201));
		gc.SetPenStyle(CGraphicsContext::ENullPen);
		gc.DrawRect(aRect);
		gc.SetBrushStyle(CGraphicsContext::ENullBrush);
		gc.SetPenColor(KRgbWhite);
		DrawMarqueeText(
				&gc, aFont,
				*narrowToWideLC(aStation->iStationNumber),
				aRect,
				(aRect.Height() + aFont->AscentInPixels()) / 2,
				CGraphicsContext::ECenter,
				0,
				iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
		CleanupStack::PopAndDestroy();
		if(!marqueeCompleted)
			iDrawer->ScheduleRedrawL(1000000/30);
		}


void CSingaporeBusDrawItemsSG::DrawDirectionL(
		const TRect& aRect, const CFont* aFont,
		const TCoordinate& aCoord1, const TCoordinate& aCoord2, TInt aAngleFromMagneticNorth) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
#ifndef __SERIES60_3X__
		if(doc->iMagneticNorthDataError != KErrNone || doc->iMagnetometerCalibrationLevel == 0)
			{
			// not calibrated
			if(doc->iMagnetometerSensor.Get())
				{
				// calibration in progress
				TRgb color ( SkinTextColor() );
				color.SetAlpha(128);
				gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( color );
				gc.SetPenStyle(CGraphicsContext::ENullPen); 
				TRect circle( aRect.Center(), TSize(0,0) );
				circle.Grow(aRect.Height()/3, aRect.Height()/3);
				gc.DrawEllipse(circle);
				}
			else
				{
				// calibration not in progress
				// draw nothing
				}
			return;
			}
		else
#endif
			{
			// calibrated
			TReal32 distance;
			aCoord1.Distance(aCoord2, distance);
			if(distance <= doc->iPositionAccuracy)
				{
				// do nothing
				}
			else
				{
				TReal32 coordBearing;
				if(aCoord1.BearingTo(aCoord2, coordBearing) == KErrNone)
					{
					TInt angle = 90 + aAngleFromMagneticNorth - coordBearing;
					
					TReal32 tan10degrees = 0.17632698070846497347109038686862;
					TReal32 sin10degrees = 0.17364817766693034885171662676931;
					if(distance*sin10degrees <= doc->iPositionAccuracy)
						{
					
					TReal precisionAngleRad;
					Math::ASin(precisionAngleRad, doc->iPositionAccuracy/distance);
					
					// angle1 = angle - precisionAngle;
					// angle2 = angle + precisionAngle;
		
					TReal cosA, sinA, cosPrecA, sinPrecA;
					Math::Cos(cosA, angle*KPi/180);
					Math::Sin(sinA, angle*KPi/180);
					Math::Cos(cosPrecA, precisionAngleRad);
					Math::Sin(sinPrecA, precisionAngleRad);
		
					TReal32 cosA1, sinA1, cosA2, sinA2;
					cosA1 = cosA*cosPrecA + sinA*sinPrecA;
					cosA2 = cosA*cosPrecA - sinA*sinPrecA;
					sinA1 = sinA*cosPrecA - cosA*sinPrecA;
					sinA2 = sinA*cosPrecA + cosA*sinPrecA;
									
					TRect circle (aRect);
					TPoint angleDir(
							circle.Height()*cosA/2,
							-circle.Height()*sinA/2
							);
					TPoint angle1Dir(
							circle.Height()*cosA1/2,
							-circle.Height()*sinA1/2
							);
					TPoint angle2Dir(
							circle.Height()*cosA2/2,
							-circle.Height()*sinA2/2
							);
					
					TRgb color ( SkinTextColor() );
					color.SetAlpha(128);
					gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( color );
					gc.SetPenStyle(CGraphicsContext::ENullPen);
					
					{
					TRect rect(circle.Center() - angleDir, TSize(0,0));
					//rect.Grow(cosPrecA*circle.Height(), cosPrecA*circle.Height());
					//rect.Grow(Max(cosPrecA*circle.Height(), circle.Height()/2), Max(cosPrecA*circle.Height(), circle.Height()/2));
					rect.Grow(circle.Height(), circle.Height());
					gc.DrawPie(
							rect,
							rect.Center() + angle1Dir,
							rect.Center() + angle2Dir);
					}
					
					TPoint arrowHead(circle.Height()*cosA/2, -circle.Height()*sinA/2);
					TPoint arrowHeadT(arrowHead.iY, -arrowHead.iX);
					TPoint arrowBranch1 = -arrowHead -arrowHeadT;
					arrowBranch1.iX /= 2;
					arrowBranch1.iY /= 2;
					TPoint arrowBranch2 = -arrowHead +arrowHeadT;
					arrowBranch2.iX /= 2;
					arrowBranch2.iY /= 2;
					TPoint polygonPoints[] = { 
							circle.Center() + arrowHead + arrowBranch1,
							circle.Center() + arrowHead,
							circle.Center() + arrowHead + arrowBranch2
					};
					gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( SkinTextColor() );
					gc.SetPenStyle(CGraphicsContext::ENullPen);
					gc.DrawPolygon(polygonPoints, sizeof(polygonPoints)/sizeof(polygonPoints[0]));
					
						}
					else
						{
						TReal cosA, sinA;
						Math::Cos(cosA, angle*KPi/180);
						Math::Sin(sinA, angle*KPi/180);
						//cosA = FastCos(angle);
						//sinA = FastSin(angle);
						const TReal sqrt2 = 1.4142135623730950488016887242097;
						TRect circle (aRect);
						TPoint polygonPoints[] =
						{
								circle.Center(), 
								circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA - sinA)/4, -circle.Height()*sqrt2*(- sinA + cosA)/4 ),
								circle.Center() + TPoint( circle.Height()*(cosA)/2, -circle.Height()*(sinA)/2 ),
								circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA + sinA)/4, -circle.Height()*sqrt2*(- sinA - cosA)/4 ),
								circle.Center()
						};
						gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( SkinTextColor() );
						gc.SetPenStyle(CGraphicsContext::ENullPen);
						gc.DrawPolygon(polygonPoints, sizeof(polygonPoints)/sizeof(polygonPoints[0]));
						}
					}
							
				}
			}
		}

void CSingaporeBusDrawItemsSG::DrawDirection4L(
		const TRect& aRect, const CFont* aFont,
		const TCoordinate& aCoord1, const TCoordinate& aCoord2, TInt aAngleFromMagneticNorth) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		TReal32 coordBearing;
		if(aCoord1.BearingTo(aCoord2, coordBearing) == KErrNone)
			{
			TReal cosA, sinA;
			TInt angle = 90 + aAngleFromMagneticNorth - coordBearing;
			Math::Cos(cosA, angle*KPi/180);
			Math::Sin(sinA, angle*KPi/180);
			//cosA = FastCos(angle);
			//sinA = FastSin(angle);
			const TReal sqrt2 = 1.4142135623730950488016887242097;
			TRect circle (aRect);
			TPoint polygonPoints[] =
			{
					circle.Center(), 
					circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA - sinA)/4, -circle.Height()*sqrt2*(- sinA + cosA)/4 ),
					circle.Center() + TPoint( circle.Height()*(cosA)/2, -circle.Height()*(sinA)/2 ),
					circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA + sinA)/4, -circle.Height()*sqrt2*(- sinA - cosA)/4 ),
					circle.Center()
			};
			gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( SkinTextColor() );
			gc.SetPenStyle(CGraphicsContext::ENullPen);
			gc.DrawPolygon(polygonPoints, sizeof(polygonPoints)/sizeof(polygonPoints[0]));
			
						
			}
		
		}

void CSingaporeBusDrawItemsSG::DrawDirection3L(
		const TRect& aRect, const CFont* aFont,
		const TCoordinate& aCoord1, const TCoordinate& aCoord2, TInt angleFromMagneticNorth) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		TReal tempAzimuthRad;
		const TReal kEpsilon = 0.00000015625; // equivalent to 1m at the equator
		if(Abs(aCoord2.Longitude() - aCoord1.Longitude()) < kEpsilon)
			{
			tempAzimuthRad = (aCoord2.Latitude() > aCoord1.Latitude()) ? KPi/2 : -KPi/2;
			}
		else
			{
			TReal tan = (aCoord2.Latitude() - aCoord1.Latitude())/(aCoord2.Longitude() - aCoord1.Longitude());
			tempAzimuthRad = FastATan(tan);
			if(aCoord2.Longitude() < aCoord1.Longitude()) tempAzimuthRad = KPi + tempAzimuthRad;
			}
		{
		
		TInt azimuth = (tempAzimuthRad*180/KPi) + angleFromMagneticNorth;
		TReal cosA, sinA;
		cosA = FastCos(azimuth*KPi/180);
		sinA = FastSin(azimuth*KPi/180);
		const TReal sqrt2 = 1.4142135623730950488016887242097;
		TRect circle (aRect);
		TPoint polygonPoints[] =
		{
				circle.Center(), 
				circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA - sinA)/4, -circle.Height()*sqrt2*(- sinA + cosA)/4 ),
				circle.Center() + TPoint( circle.Height()*(cosA)/2, -circle.Height()*(sinA)/2 ),
				circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA + sinA)/4, -circle.Height()*sqrt2*(- sinA - cosA)/4 ),
				circle.Center()
		};
		gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( SkinTextColor() );
		gc.SetPenStyle(CGraphicsContext::ENullPen);
		gc.DrawPolygon(polygonPoints, sizeof(polygonPoints)/sizeof(polygonPoints[0]));
		
		{
		gc.UseFont( (const CFont*)AknLayoutUtils::LayoutFontFromId(EAknLogicalFontPrimarySmallFont) );
		TBuf<128> buf;
		gc.SetPenColor(KRgbRed);
		buf.Format(_L("%d, %d"), angleFromMagneticNorth, (360 + 90 - (TInt)(tempAzimuthRad*180/KPi))%360);
		gc.DrawText(buf, TPoint(aRect.iTl.iX, aRect.iBr.iY - 20));
		TReal32 angle;
		aCoord1.BearingTo(aCoord2, angle);
		buf.Format(_L("%d"), (TInt)angle);
		gc.DrawText(buf, TPoint(aRect.iTl.iX, aRect.iBr.iY - 40));
		}
		
		}
}


void CSingaporeBusDrawItemsSG::DrawDirection2L(
		const TRect& aRect, const CFont* aFont,
		const TCoordinate& aCoord1, const TCoordinate& aCoord2, TInt angleFromMagneticNorth) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		TReal tempAzimuthRad;
		const TReal kEpsilon = 0.00000015625; // equivalent to 1m at the equator
		if(Abs(aCoord2.Longitude() - aCoord1.Longitude()) < kEpsilon)
			{
			tempAzimuthRad = (aCoord2.Latitude() > aCoord1.Latitude()) ? KPi/2 : -KPi/2;
			}
		else
			{
			TReal tan = (aCoord2.Latitude() - aCoord1.Latitude())/(aCoord2.Longitude() - aCoord1.Longitude());
			Math::ATan(tempAzimuthRad, tan);
			if(aCoord2.Longitude() < aCoord1.Longitude()) tempAzimuthRad = KPi + tempAzimuthRad;
			}
		{
		
		TInt azimuth = (tempAzimuthRad*180/KPi) + angleFromMagneticNorth;
		TReal cosA, sinA;
		Math::Cos(cosA, azimuth*KPi/180);
		Math::Sin(sinA, azimuth*KPi/180);
		const TReal sqrt2 = 1.4142135623730950488016887242097;
		TRect circle (aRect);
		TPoint polygonPoints[] =
		{
				circle.Center(), 
				circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA - sinA)/4, -circle.Height()*sqrt2*(- sinA + cosA)/4 ),
				circle.Center() + TPoint( circle.Height()*(cosA)/2, -circle.Height()*(sinA)/2 ),
				circle.Center() + TPoint( circle.Height()*sqrt2*(- cosA + sinA)/4, -circle.Height()*sqrt2*(- sinA - cosA)/4 ),
				circle.Center()
		};
		gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor( SkinTextColor() );
		gc.SetPenStyle(CGraphicsContext::ENullPen);
		gc.DrawPolygon(polygonPoints, sizeof(polygonPoints)/sizeof(polygonPoints[0]));
		
		{
		gc.UseFont( (const CFont*)AknLayoutUtils::LayoutFontFromId(EAknLogicalFontPrimarySmallFont) );
		TBuf<128> buf;
		gc.SetPenColor(KRgbRed);
		buf.Format(_L("%d, %d"), angleFromMagneticNorth, (360 + 90 - (TInt)(tempAzimuthRad*180/KPi))%360);
		gc.DrawText(buf, TPoint(aRect.iTl.iX, aRect.iBr.iY - 20));
		TReal32 angle;
		aCoord1.BearingTo(aCoord2, angle);
		buf.Format(_L("%d"), (TInt)angle);
		gc.DrawText(buf, TPoint(aRect.iTl.iX, aRect.iBr.iY - 40));
		}
		
		}
}


void CSingaporeBusDrawItemsSG::DrawDistanceL(
		const TRect& aRect, const CFont* aFont,
		const TCoordinate& aCoord1, const TCoordinate& aCoord2) const
		{
		CWindowGc& gc = *iDrawer->Gc();
		TBool marqueeCompleted = EFalse;
		TBuf<128> distanceBuf;
		TReal32 distance;
		aCoord1.Distance(aCoord2, distance);
		AppendFormatDistanceL(distanceBuf, distance);
		gc.SetBrushStyle(CGraphicsContext::ENullBrush);
		gc.SetPenColor(SkinTextColor());
		DrawMarqueeText(
				&gc, aFont,
				distanceBuf,
				aRect,
				(aRect.Height() + aFont->AscentInPixels()) / 2,
				CGraphicsContext::ECenter,
				0,
				iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
		if(!marqueeCompleted)
			iDrawer->ScheduleRedrawL(1000000/30);
}

void CSingaporeBusDrawItemsSG::DrawTextL(
		const TRect& aRect, const CFont* aFont,
		const TDesC8& aText, CGraphicsContext::TTextAlign aAlign) const
{
	CWindowGc& gc = *iDrawer->Gc();
	TBool marqueeCompleted = EFalse;
	gc.SetBrushStyle(CGraphicsContext::ENullBrush);
	gc.SetPenColor(SkinTextColor());
	DrawMarqueeText(
			&gc, aFont,
			*narrowToWideLC(aText),
			aRect,
			(aRect.Height() + aFont->AscentInPixels() - aFont->DescentInPixels()) / 2,
			aAlign,
			0,
			iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
	CleanupStack::PopAndDestroy();
	if(!marqueeCompleted)
		iDrawer->ScheduleRedrawL(1000000/30);
}

void CSingaporeBusDrawItemsSG::DrawTextL(
		const TRect& aRect, const CFont* aFont,
		const TDesC& aText, CGraphicsContext::TTextAlign aAlign) const
{
	CWindowGc& gc = *iDrawer->Gc();
	TBool marqueeCompleted = EFalse;
	gc.SetBrushStyle(CGraphicsContext::ENullBrush);
	gc.SetPenColor(SkinTextColor());
	DrawMarqueeText(
			&gc, aFont,
			aText,
			aRect,
			(aRect.Height() + aFont->AscentInPixels()) / 2,
			aAlign,
			0,
			iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
	if(!marqueeCompleted)
		iDrawer->ScheduleRedrawL(1000000/30);
}

void CSingaporeBusDrawItemsSG::DrawArrivalTimeL(
		const TRect& aRect, const CFont* aFont,
		const CArrivalTimeItem* aArrivalTime) const
{
	CWindowGc& gc = *iDrawer->Gc();
	TBool marqueeCompleted = EFalse;
	TBuf<1024> requestBuf;
	switch(aArrivalTime->iRequestStatus)
		{
		case CArrivalTimeQuery::ERequestWait:
			requestBuf.AppendFormat(_L("select to request"));
			break;
		case CArrivalTimeQuery::ERequestPending:
			requestBuf.AppendFormat(_L("requesting..."));
			break;
		case CArrivalTimeQuery::ERequestPendingInitialization:
			requestBuf.AppendFormat(_L("waiting initialisation..."));
			break;
		case CArrivalTimeQuery::ERequestCompleted:
			requestBuf.AppendFormat(_L("%S"), aArrivalTime->iNextBus);
			if(aArrivalTime->iSubsequentBus->Length())
				requestBuf.AppendFormat(_L(" \xf814 %S"), aArrivalTime->iSubsequentBus);
			break;
		case CArrivalTimeQuery::ERequestUnavailable:
			requestBuf.AppendFormat(_L("arrival time unavailable"));
			break;
		case CArrivalTimeQuery::ERequestError:
			requestBuf.AppendFormat(_L("error (%S, %S)"), aArrivalTime->iNextBus, aArrivalTime->iSubsequentBus);
			break;
		}
	DrawMarqueeText(
			&gc, aFont,
			requestBuf,
			aRect,
			(aRect.Height() + aFont->AscentInPixels()) / 2,
			CGraphicsContext::ECenter,
			0,
			iItemIsCurrent ? iIntervalSincePreviousCurrentItemChange : TTimeIntervalMicroSeconds(KMaxTInt64), marqueeCompleted);
	if(!marqueeCompleted)
		iDrawer->ScheduleRedrawL(1000000/30);
}


void CSingaporeBusDrawItemsSG::DrawIconL(
		const TRect& aRect,
		TInt aIconIndex) const
{
	CWindowGc& gc = *iDrawer->Gc();
	if((*iDrawer->IconArray())[aIconIndex]->Bitmap()->SizeInPixels() != aRect.Size())
		AknIconUtils::SetSize( (*iDrawer->IconArray())[aIconIndex]->Bitmap(), aRect.Size(), EAspectRatioPreserved );
	gc.SetBrushStyle(CGraphicsContext::ENullBrush);
	gc.BitBltMasked(aRect.iTl, (*iDrawer->IconArray())[aIconIndex]->Bitmap(), (*iDrawer->IconArray())[aIconIndex]->Bitmap()->SizeInPixels(), (*iDrawer->IconArray())[aIconIndex]->Mask(), EFalse);
}


void CSingaporeBusDrawItemsSG::DrawBackgroundL(
		const TRect& aRect) const
{
	CWindowGc& gc = *iDrawer->Gc();
	
//#ifdef __SERIES60_3X__ // Symbian^3 does not define that macro
//	// Symbian^3 automatically draws the background
	MAknsControlContext* controlContext = NULL;
	iDrawer->ListBox()->MopGetObject(controlContext);
	if(controlContext)
	{
	 AknsDrawUtils::Background(AknsUtils::SkinInstance(),
	 controlContext, 
	 iDrawer->ListBox(), 
	 gc, 
	 aRect
	 );
	}
//#endif
	if(iItemIsCurrent)
		{
		TRect innerFrame = aRect;
		innerFrame.Shrink(aRect.Height()/10, aRect.Height()/10);
		AknsDrawUtils::DrawFrame(AknsUtils::SkinInstance(), gc, aRect, innerFrame, KAknsIIDQsnFrList, KAknsIIDQsnFrListCenter);
		}
}


const TRgb& CSingaporeBusDrawItemsSG::SkinTextColor() const
{
	if(!iValidSkinTextColor)
		{
		AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), iSkinTextColor, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG9 );
		AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), iSkinHighlightTextColor, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG11 );
		iValidSkinTextColor = ETrue;
		}
	return iItemIsCurrent ? iSkinHighlightTextColor : iSkinTextColor;
}

CSingaporeBusDrawItemsSG::~CSingaporeBusDrawItemsSG()
	{
	if(iPrimaryFont)
		CCoeEnv::Static()->ScreenDevice()->ReleaseFont(iPrimaryFont);
	if(iSecondaryFont)
		CCoeEnv::Static()->ScreenDevice()->ReleaseFont(iSecondaryFont);
	}
